package main;

import proxy.Configuration;
import proxy.Configuration.CleanUpType;
import proxy.HormoneControls;
import proxy.VideoUnit;
import simulation.Simulator;
import simulation.SimulatorConfig;
import simulation.SimulatorConfig.GraphGenerator;
import simulation.SimulatorConfig.PresentationMode;
import simulation.SimulatorConfig.ReplicationType;
import simulation.SimulatorConfig.ScenarioType;

/**
 * Class to define scenarios and to configure them - examples are below
 * @author Anita
 *
 */
public class DefaultConfig {

	// default config - use inner classes for new scenarios!
	int numRuns = 10;
	int nServers = 100;
	int consumersPerServerMax = 1;
	
	int simTime = 5000; //sec
	long bandwidth = 100000; //bytes
	boolean nodeFailure = false;
	double churnProbability = 1; //probability of churn per time step if nodefailure = true
	double fillServerRate = 0.1;
	double diskFullCleanupLimit = 0.31;
	
	//how often should statistics be written to the file (every time step?)
	int reportingGranularity = 1;
	
	ScenarioType scenario = ScenarioType.SEARCH;
	PresentationMode mode = PresentationMode.SEQ;
	ReplicationType repType = ReplicationType.HRATING;
	GraphGenerator graphType = GraphGenerator.RANDOM;
	CleanUpType cleanupType = CleanUpType.HORMONE;
	boolean sortTransmissionAccordingToHormones = true;
	
	//has to be made in every configuration
	private Double[] hormoneInput = { 0.1, 0.1, 0.5 };
	HormoneControls contr = new HormoneControls(hormoneInput);
	
	boolean withGeneralization = false;
	boolean consumerCorrelation = false;
	
	boolean withHormoneVisualization = false;
			
	boolean directDownload = false;
		
	
	boolean useCleanup = true;
	boolean log = false;

	
	Simulator initSimulator(int seed) {
		Configuration conf = new Configuration(cleanupType,
				sortTransmissionAccordingToHormones, 900000000,
				withGeneralization);
		conf.setDiskfullCleanupLimit(diskFullCleanupLimit);
		conf.setDirectDownload(directDownload);

		SimulatorConfig config = new SimulatorConfig(nServers);
		config.setConsumersPerServerMax(consumersPerServerMax);
		config.setDefaultDatarate(bandwidth / 8.0);
		config.setMode(mode);
		config.setRand(seed);
		config.setLogActivate(log);
		config.setScenario(scenario);
		config.setFillServerRate(fillServerRate);
		config.setRep(repType);
		config.setGraphgen(graphType);
		config.setCleanup(useCleanup);

		Simulator simulator = new Simulator(config, conf, contr);
		// System.out.println("Nodes have been created..");

		// simulator.writeUnitsToFile("units" + nServers + ".txt");
		return simulator;
	}
}

/**
 * Scenario: RandomNetwork with different replication types
 * @author Anita
 *
 */
class ReplicationConfigRandom extends DefaultConfig {
	public ReplicationConfigRandom() {
		super();
		init();
	}

	// wises/saso/tr
	private void init() {
		bandwidth = 1000000;
		numRuns = 10;
		nServers = 50;
		simTime = 5000;
		scenario = ScenarioType.SEARCH; // matches content not unit ids
		mode = PresentationMode.SIMP;
		repType = ReplicationType.HRATING; //configure here
		graphType = GraphGenerator.RANDOM;
		withGeneralization = false;
		cleanupType = CleanUpType.HORMONE;
		fillServerRate = 0.3;
		diskFullCleanupLimit = 0.6;
		consumerCorrelation = false;
		consumersPerServerMax = 1;
		useCleanup = false;
	}
}

/**
 * Scenario: Random network with different replication Types - sequential requests
 * @author Anita
 *
 */
class ReplicationConfigRandomSeq extends DefaultConfig {
	public ReplicationConfigRandomSeq() {
		super();
		init();
	}

	private void init() {
		Double[] test = { 0.1, 0.1, 0.5 };

		contr = new HormoneControls(test);
		numRuns = 1;
		nServers = 50;
		simTime = 500;
		log = true;
		scenario = ScenarioType.SEARCH;
		mode = PresentationMode.SEQ;
		repType = ReplicationType.HRATING;
		graphType = GraphGenerator.RANDOM;
		cleanupType = CleanUpType.HORMONE;
		fillServerRate = 0.005;
		diskFullCleanupLimit = 0.30;
		consumerCorrelation = false;
		consumersPerServerMax = 1;
		withGeneralization = false;
		VideoUnit.setVideoBitRate(1000000);
		VideoUnit.setMinSize(125000);
		VideoUnit.setAvgSize(125000);
		VideoUnit.setStdevSize(0);
		VideoUnit.setMaxSize(125000);
		bandwidth = 1000000;
	}
}

/**
 * Investigate different unit sizes and their impact on delivery 
 * @author Anita
 *
 */
class UnitSizeConfig extends DefaultConfig {

	public UnitSizeConfig() {
		super();
		init();
	}

	private void init() {
		numRuns = 3;
		nServers = 100;
		simTime = 5000;

		// scenario = ScenarioType.UNITSIZEREFSEARCH;
		// repType = ReplicationType.OWNER;
		// cleanupType = CleanUpType.LRU;
		// directDownload = true;

		scenario = ScenarioType.UNITSIZE;
		repType = ReplicationType.HRATING;
		cleanupType = CleanUpType.HORMONE;

		mode = PresentationMode.SEQ;
		graphType = GraphGenerator.SCALEFRE;

		fillServerRate = 0.01;
		diskFullCleanupLimit = 0.10;
		consumersPerServerMax = 1;
		consumerCorrelation = false;
		withGeneralization = false;
		// WLAN: netto: 20 MBit/sec upload und download geteilt
		// ADSL:up 1-2 MBit/sec (down - 10-20Mbit)
		// Cable: up: 3 MBit/sec
		// 3G: up:0.5-1Mbit/sec
		// 4G: 5 MBit/sec
		bandwidth = 1000000;
		// QCIF: 200kbit/sec
		// LNF: 1Mbit/sec
		// 640x480 2Mbit/sec
		VideoUnit.setVideoBitRate(200000);
		// VideoUnit.setVideoBitRate(1000000);

		// 250KB
		VideoUnit.setMinSize(256000);
		VideoUnit.setAvgSize(256000);
		VideoUnit.setStdevSize(0);
		VideoUnit.setMaxSize(256000);

		// 128KB
		// VideoUnit.setMinSize(128000);
		// VideoUnit.setAvgSize(128000);
		// VideoUnit.setStdevSize(0);
		// VideoUnit.setMaxSize(128000);

		// 512KB
		// VideoUnit.setMinSize(512000);
		// VideoUnit.setAvgSize(512000);
		// VideoUnit.setStdevSize(0);
		// VideoUnit.setMaxSize(512000);

		// 56KB
		// VideoUnit.setMinSize(56000);
		// VideoUnit.setAvgSize(56000);
		// VideoUnit.setStdevSize(0);
		// VideoUnit.setMaxSize(56000);
		//
		// 1024
		// VideoUnit.setMinSize(1024000);
		// VideoUnit.setAvgSize(1024000);
		// VideoUnit.setStdevSize(0);
		// VideoUnit.setMaxSize(1024000);

		// variable settings
		// LNF

	}

}

/**
 * Scenario: Replication with churn
 * @author Anita
 *
 */
class ReplicationConfigRandomChurn extends DefaultConfig {
	public ReplicationConfigRandomChurn() {
		super();
		init();
	}

	private void init() {

		Double[] test = { 0.1, 0.1, 0.5 };

		contr = new HormoneControls(test);
		numRuns = 16;
		nServers = 50;
		simTime = 500;
		log = false;
		scenario = ScenarioType.SEARCH;
		mode = PresentationMode.SEQ;
		repType = ReplicationType.HRATING;
		graphType = GraphGenerator.RANDOM;
		cleanupType = CleanUpType.HORMONE;
		fillServerRate = 0.005;
		diskFullCleanupLimit = 0.30;
		consumerCorrelation = false;
		consumersPerServerMax = 1;
		withGeneralization = false;
		VideoUnit.setVideoBitRate(1000000);
		VideoUnit.setMinSize(125000);
		VideoUnit.setAvgSize(125000);
		VideoUnit.setStdevSize(0);
		VideoUnit.setMaxSize(125000);
		bandwidth = 1000000;
		nodeFailure = true; //configure here
		churnProbability = 10; //number of nodes leaving/joining the system during simulation

	}
}

/**
 * Scenario: Replication in Scale-Free Network
 * @author Anita
 *
 */
class ReplicationConfigScaleFree extends DefaultConfig {
	public ReplicationConfigScaleFree() {
		super();
		init();
	}

	private void init() {
		numRuns = 1;
		nServers = 1000;
		simTime = 7000;
		scenario = ScenarioType.SEARCH;
		mode = PresentationMode.SIMP;
		repType = ReplicationType.HRATING;
		graphType = GraphGenerator.SCALEFRE;
		withGeneralization = false;
		cleanupType = CleanUpType.HORMONE;
		fillServerRate = 0.03;
		diskFullCleanupLimit = 0.51;
		consumerCorrelation = false;
		nodeFailure = true;
		churnProbability = 500;
	}
}

/**
 * Scenario: Matches concrete unit id
 * @author Anita
 *
 */
class SingleUnitConfig extends DefaultConfig {

	public SingleUnitConfig() {
		super();
		init();
	}

	private void init() {
		nServers = 10;
		simTime = 1000;
		numRuns = 2;
		scenario = ScenarioType.SIMPLEHORMONE;
		mode = PresentationMode.SEQ;
		graphType = GraphGenerator.RANDOM;
		withGeneralization = false;
		contr = null;
		fillServerRate = 0.01;
		diskFullCleanupLimit = 0.51;
		consumerCorrelation = false;
	}
}

/**
 * Reference model with iterative deepening search - plus content matching
 * @author Anita
 *
 */
class RefSearchDirectDownloadConfig extends DefaultConfig {
	public RefSearchDirectDownloadConfig() {
		super();
		init();
	}

	private void init() {
		numRuns = 1;
		nServers = 50;
		simTime = 5000;
		scenario = ScenarioType.REFSEARCH;
		mode = PresentationMode.SEQ;
		graphType = GraphGenerator.RANDOM;
		withGeneralization = false;
		cleanupType = CleanUpType.LRU;
		fillServerRate = 0.3;
		diskFullCleanupLimit = 0.59;
		consumerCorrelation = false;
		directDownload = true;
		sortTransmissionAccordingToHormones = false;
	}
}

/**
 * Scenario: Information Dissemination - One information unit has to spread as fast as possible through the network
 * @author Anita
 * ISSUE - content matching for delivery, client matches for id - if two nodes have the same content coverage is not guaranteed
 */
class InformationDisseminationConfig extends DefaultConfig {
	public InformationDisseminationConfig() {
		super();
		init();
	}

	private void init() {
		//diffiusion, evaporation, busylink - for full coverage evaporation has to be 0!
		Double[] hormones = {0.1, 0.0, 0.0 }; //values are derived from parameter study
		contr = new HormoneControls(hormones);
		
		numRuns = 10; //for > 90 % confidence
		nServers = 100; 
		simTime = 30; //max. number of rounds 
		
		nodeFailure = false; //churn - random peer-churn - over simTime regularly a node is added or removed
		churnProbability = 0; //probability that a node is added or removed per time step if nodeFailure is true
		
		scenario = ScenarioType.DISSEMINATION; //Choose Scenario here - GOSSIP or DISSEMINATION
		
		fillServerRate = 0.0001; //we fill every server with one unit - since we only want to distribute u0
		
		log = false;
		
		//size and bandwidth are chosen such that the transport of one unit matches one time step
		VideoUnit.setAvgSize(125000);
		VideoUnit.setMaxSize(125000);
		VideoUnit.setMinSize(125000);
		bandwidth = 1000000;
		

		
	}
}